In this vignette, we demonstrate the capability of SCEG-HiC to infer enhancer–gene links by applying it to paired scATAC-seq/RNA-seq data. Specifically, we use a publicly available SHARE-seq dataset for mouse skin and process the data using the aggregation approach.
The implementation of SCEG-HiC is seamlessly compatible with the standard workflow of the Seurat/Signac packages. The SCEG-HiC pipeline consists of the following three main steps:
Set up the Seurat object: Prepare and preprocess paired single-cell multi-omics data using the Seurat and Signac framework.
Infer enhancer–gene links: Apply the SCEG-HiC model to the processed Seurat object, incorporating mouse bulk average Hi-C data as a chromatin conformation prior to enhance the inference of enhancer–gene links.
Visualize enhancer–gene links: Generate graphical outputs such as arc diagrams and coverage plots to visualize predicted enhancer–gene links.
You can download the required data from GSE140203 by running the following commands in a shell:
wget https://ftp.ncbi.nlm.nih.gov/geo/samples/GSM4156nnn/GSM4156597/suppl/GSM4156597%5Fskin.late.anagen.peaks.bed.gz
wget https://ftp.ncbi.nlm.nih.gov/geo/samples/GSM4156nnn/GSM4156597/suppl/GSM4156597%5Fskin.late.anagen.barcodes.txt.gz
wget https://ftp.ncbi.nlm.nih.gov/geo/samples/GSM4156nnn/GSM4156597/suppl/GSM4156597%5Fskin.late.anagen.counts.txt.gz
wget https://ftp.ncbi.nlm.nih.gov/geo/samples/GSM4156nnn/GSM4156597/suppl/GSM4156597%5Fskin%5Fcelltype.txt.gz
wget https://ftp.ncbi.nlm.nih.gov/geo/samples/GSM4156nnn/GSM4156608/suppl/GSM4156608%5Fskin.late.anagen.rna.counts.txt.gz
wget https://ftp.ncbi.nlm.nih.gov/geo/samples/GSM4156nnn/GSM4156597/suppl/GSM4156597%5Fskin.late.anagen.atac.fragments.bed.gz
The SHARE-seq dataset requires preprocessing to obtain the fragment file needed for downstream analysis. You can generate this file by running the following commands in a shell:
# Decompress the original gzipped fragment file
gunzip GSM4156597_skin.late.anagen.atac.fragments.bed.gz
# Replace all commas with dots to fix formatting issues
sed -i "s/,/./g" GSM4156597_skin.late.anagen.atac.fragments.bed
# Sort the BED file by chromosome (version sort), start, and end; count unique occurrences; rearrange columns to place counts last; compress output with bgzip
sort -k1,1V -k2,2n -k3,3n GSM4156597_skin.late.anagen.atac.fragments.bed | uniq -c | awk '{print $2,$3,$4,$5,$1}' OFS="\t" | bgzip -c > GSM4156597_skin.late.anagen.atac.fragments.mybed.gz
# Index the compressed BED file using tabix for fast access during downstream analysis
# Before indexing, make sure tabix is installed. You can install it via Conda: conda install bioconda::tabix
tabix -0 -p bed GSM4156597_skin.late.anagen.atac.fragments.mybed.gz
library(SCEGHiC)
library(Seurat)
library(Signac)
library(EnsDb.Mmusculus.v79) # Annotation for mouse skin
library(dplyr)
library(Matrix)
library(GenomicRanges)
library(ggplot2)
To facilitate easy exploration, mouse_skin_multiomic.rds
file is also available at 10.5281/zenodo.14849886.
Note: Due to the stochastic nature of
SCTransform, particularly in generating
scale.data, the UMAP embedding produced by re-running the
code may differ slightly from that in the provided
mouse_skin_multiomic.rds file.
Construct a Seurat object combining RNA expression and ATAC-seq chromatin accessibility data, annotated with cell types based on the original study and genome features from mm10.
# Create a Seurat object containing the RNA count matrix (assay named "RNA")
skin <- CreateSeuratObject(counts = rna.count, assay = "RNA")
# Filter peaks to keep only those on standard chromosomes,
# removing any peaks from non-standard or unplaced contigs
grange.use <- seqnames(peak.granges) %in% standardChromosomes(peak.granges)
peak.count <- peak.count[as.vector(grange.use), ]
peak.granges <- peak.granges[as.vector(grange.use)]
# Get gene annotations from EnsDb.Mmusculus.v79
# Add "chr" prefix to chromosome names to match peak naming conventions
annotations <- GetGRangesFromEnsDb(ensdb = EnsDb.Mmusculus.v79)
seqlevels(annotations) <- paste0("chr", seqlevels(annotations))
genome(annotations) <- "mm10"
# Filter out peaks detected in fewer than 10 cells
peak.count <- peak.count[rowSums(peak.count) > 10, ]
# Specify the path to the ATAC-seq fragments file
fragpath <- "GSM4156597_skin.late.anagen.atac.fragments.mybed.gz"
# Create an ATAC assay using the filtered peak counts and annotations, and add it to the Seurat object
skin[["ATAC"]] <- CreateChromatinAssay(
counts = peak.count,
sep = c(":", "-"),
fragments = fragpath,
genome = "mm10",
annotation = annotations
)
# Annotate cell types for each cell in the Seurat object based on the 'ct' table, matching cell names from the Seurat object with those in 'ct'
skin$celltype <- ct[match(colnames(skin), ct[, 1]), 3]
# Print summary of the filtered Seurat object
skin
## An object of class Seurat
## 367087 features across 34774 samples within 2 assays
## Active assay: RNA (23296 features, 0 variable features)
## 1 layer present: counts
## 1 other assay present: ATAC
Calculate QC metrics (RNA counts, ATAC counts, mitochondrial percentage, nucleosome signal, TSS enrichment) and filter low-quality cells using defined thresholds.
# Calculate the percentage of mitochondrial gene counts for each cell
# Mitochondrial genes typically start with "MT-"
skin[["percent.mt"]] <- PercentageFeatureSet(skin, pattern = "^MT-")
# Set default assay to ATAC for ATAC-seq quality metrics calculation
DefaultAssay(skin) <- "ATAC"
# Calculate nucleosome signal score, which reflects nucleosome positioning
skin <- NucleosomeSignal(skin)
# Calculate Transcription Start Site (TSS) enrichment score for each cell, a metric for ATAC-seq data quality
skin <- TSSEnrichment(skin)
# Plot violin plots for QC metrics:
# - RNA counts per cell (nCount_RNA)
# - ATAC counts per cell (nCount_ATAC)
# - TSS enrichment score (TSS.enrichment)
# - Nucleosome signal score (nucleosome_signal)
VlnPlot(
object = skin,
features = c("nCount_RNA", "nCount_ATAC", "TSS.enrichment", "nucleosome_signal"),
ncol = 4,
pt.size = 0
)
# Filter out low-quality cells based on multiple QC thresholds
skin <- subset(
x = skin,
subset = nCount_ATAC < 20000 &
nCount_RNA < 5000 &
nCount_ATAC > 500 &
nCount_RNA > 500 &
nucleosome_signal < 1 &
TSS.enrichment > 1
)
# Print summary of the filtered Seurat object
skin
## An object of class Seurat
## 367087 features across 28821 samples within 2 assays
## Active assay: ATAC (343791 features, 0 variable features)
## 2 layers present: counts, data
## 1 other assay present: RNA
Call peaks, filter, count fragments per peak, and add to Seurat object.
# Call peaks using MACS2 from the fragments in the Seurat object
peaks <- CallPeaks(skin)
# Remove peaks on nonstandard chromosomes and in genomic blacklist regions
peaks <- keepStandardChromosomes(peaks, pruning.mode = "coarse")
peaks <- subsetByOverlaps(x = peaks, ranges = blacklist_mm10, invert = TRUE)
# Quantify counts of fragments overlapping each peak for each cell, creating a peak-by-cell count matrix
macs2_counts <- FeatureMatrix(
fragments = Fragments(skin),
features = peaks,
cells = colnames(skin)
)
## Extracting reads overlapping genomic regions
# Create a new chromatin assay based on MACS2-called peaks and add it to the Seurat object
skin[["peaks"]] <- CreateChromatinAssay(
counts = macs2_counts,
fragments = fragpath,
annotation = annotations
)
## Computing hash
# Print summary of the updated Seurat object
skin
## An object of class Seurat
## 562259 features across 28821 samples within 3 assays
## Active assay: ATAC (343791 features, 0 variable features)
## 2 layers present: counts, data
## 2 other assays present: RNA, peaks
Normalize RNA data with SCTransform and perform PCA for dimensionality reduction.
# Set the default assay to "RNA" for RNA-based analysis
DefaultAssay(skin) <- "RNA"
# Perform normalization and variance stabilization using SCTransform
# This replaces traditional log-normalization and identifies variable features
skin <- SCTransform(skin)
# Run Principal Component Analysis (PCA) on the normalized data
# PCA reduces dimensionality while preserving major sources of variation
skin <- RunPCA(skin)
Identify highly accessible peaks and perform dimensionality reduction using TF-IDF and SVD (LSI).
# Set the default assay to "peaks" (i.e., the MACS2-called peak matrix)
DefaultAssay(skin) <- "peaks"
# Identify top features (peaks) based on accessibility; only keep peaks present in at least 5 cells
skin <- FindTopFeatures(skin, min.cutoff = 5)
# Perform Term Frequency-Inverse Document Frequency (TF-IDF) normalization
skin <- RunTFIDF(skin)
# Perform dimensionality reduction using Singular Value Decomposition (SVD), also referred to as Latent Semantic Indexing (LSI) in this context
skin <- RunSVD(skin)
Using Seurat v4’s weighted nearest neighbor method, we integrate gene expression and chromatin accessibility into a joint neighbor graph and create a unified UMAP embedding combining RNA and ATAC data.
# Build a multimodal nearest-neighbor graph using PCA from RNA and LSI from ATAC
skin <- FindMultiModalNeighbors(
object = skin,
reduction.list = list("pca", "lsi"),
dims.list = list(1:50, 2:40),
modality.weight.name = "RNA.weight",
verbose = TRUE
)
# Generate a joint UMAP embedding using the WNN graph
# The embedding combines information from both RNA and ATAC modalities
skin <- RunUMAP(
object = skin,
nn.name = "weighted.nn",
assay = "RNA",
verbose = TRUE
)
# Visualize the UMAP embedding, grouping cells by annotated cell type
DimPlot(skin, reduction = "umap", group.by = "celltype", label = TRUE, label.size = 2.5, repel = TRUE) + NoLegend()
To prepare for SCEG-HiC analysis, we process paired scATAC-seq/RNA-seq data stored in a Seurat object. Here, we use the aggregation approach to handle paired scATAC-seq/RNA-seq data. By default, the scATAC-seq counts are binarized to indicate the presence or absence of chromatin accessibility at each peak.
# Prepare input data for SCEG-HiC analysis
# This function processes paired paired scATAC-seq/RNA-seq data stored in a Seurat object
SCEGdata <- process_data(skin, cellnames = "celltype", max_overlap = 0.5)
## Generating aggregated data
## Aggregating cluster Dermal Fibroblast
## Sample cells randomly.
## There are 20 samples
## Aggregating cluster Dermal Papilla
## Sample cells randomly.
## There are 13 samples
## Aggregating cluster TAC-1
## Sample cells randomly.
## There are 60 samples
## Aggregating cluster Mix
## Sample cells randomly.
## There are 53 samples
## Aggregating cluster IRS
## Sample cells randomly.
## There are 15 samples
## Aggregating cluster Basal
## Sample cells randomly.
## Warning in asMethod(object): sparse->dense coercion: allocating vector of size
## 1.1 GiB
## There are 131 samples
## Aggregating cluster K6+ Bulge Companion Layer
## Sample cells randomly.
## There are 9 samples
## Aggregating cluster Medulla
## Sample cells randomly.
## There are 18 samples
## Aggregating cluster alowCD34+ bulge
## Sample cells randomly.
## There are 35 samples
## Aggregating cluster Isthmus
## Sample cells randomly.
## There are 13 samples
## Aggregating cluster ORS
## Sample cells randomly.
## There are 20 samples
## Aggregating cluster Infundibulum
## Sample cells randomly.
## There are 73 samples
## Aggregating cluster Spinous
## Sample cells randomly.
## There are 53 samples
## Aggregating cluster ahighCD34+ bulge
## Sample cells randomly.
## There are 29 samples
## Aggregating cluster TAC-2
## Sample cells randomly.
## There are 20 samples
## Aggregating cluster Macrophage DC
## Sample cells randomly.
## There are 4 samples
## Aggregating cluster Endothelial
## Sample cells randomly.
## There are 17 samples
## Aggregating cluster Dermal Sheath
## Sample cells randomly.
## There are 8 samples
## Aggregating cluster Sebaceous Gland
## Sample cells randomly.
## There are 4 samples
## Aggregating cluster Granular
## Sample cells randomly.
## There are 5 samples
## Aggregating cluster Hair Shaft-cuticle.cortex
## Sample cells randomly.
## There are 23 samples
## Aggregating cluster Schwann Cell
## Sample cells randomly.
## There are 3 samples
## Aggregating cluster Melanocyte
## Sample cells randomly.
## There are 4 samples
Calculating weights with SCEG-HiC can be time-consuming, especially as the number of selected genes increases. To facilitate this process, SCEG-HiC provides downloadable average Hi-C datasets for both human and mouse (detail here). In this case, we select the mouse average Hi-C data as prior information to calculate enhancer-gene interaction weights.
You can focus on the top 3000 highly variable genes identified by SCTransform normalization:
# Extract highly variable genes
gene <- skin@assays[["SCT"]]@var.features
# Calculate Hi-C weights for these genes using mouse average Hi-C data
weight <- calculateHiCWeights(SCEGdata, species = "Mus musculus", genome = "mm10", focus_gene = gene, averHicPath = "/picb/bigdata/project/liangxuan/data/mouse_contact/average")
As an example, we calculate Hi-C weights focusing on Basal cell marker genes (e.g., Krt5, Krt14).
# Alternatively, calculate Hi-C weights for specific marker genes of Basal cells (e.g. Krt5, Krt14)
weight <- calculateHiCWeights(SCEGdata, species = "Mus musculus", genome = "mm10", focus_gene = c("Krt5", "Krt14"), averHicPath = "/picb/bigdata/project/liangxuan/data/mouse_contact/average")
## Processing chromosome chr11...
## Found 1 TSS loci on chr11.
## Calculating Hi-C weights for gene Krt14...
## Processing chromosome chr15...
## Found 1 TSS loci on chr15.
## Calculating Hi-C weights for gene Krt5...
## Finished calculating Hi-C weights for all genes.
SCEG-HiC employs the wglasso method to infer enhancer-gene links by integrating processed single-cell multi-omics data and normalized bulk average Hi-C contact matrices. The bulk Hi-C matrix is normalized using rank score to improve accuracy. In this example, we run the model focusing on Basal cell marker genes Krt5 and Krt14 to identify their putative enhancer links.
# Example: Run the model focused on Basal cell markers Krt5 and Krt14
results_SCEGHiC <- Run_SCEG_HiC(SCEGdata, weight, focus_gene = c("Krt5", "Krt14"))
## Total predicted genes: 2
## Running model for gene: Krt14
## [1] "The optimal penalty parameter (rho) selected by BIC is: 0.26"
## Running model for gene: Krt5
## [1] "The optimal penalty parameter (rho) selected by BIC is: 0.27"
Arc plot visualizes the predicted links between enhancers and target genes as arcs connecting genomic regions, highlighting spatial chromatin interactions inferred by SCEG-HiC.
# Download and prepare gene annotation data
# wget https://hgdownload2.soe.ucsc.edu/goldenPath/mm10/bigZips/genes/mm10.refGene.gtf.gz
temp <- "mm10.refGene.gtf.gz"
gene_anno <- rtracklayer::readGFF(temp)
# Rename some columns to match requirements
gene_anno$chromosome <- gene_anno$seqid
gene_anno$gene <- gene_anno$gene_id
gene_anno$transcript <- gene_anno$transcript_id
gene_anno$symbol <- gene_anno$gene_name
Arc plot visualization of enhancer-gene links for Krt5.
connections_Plot(results_SCEGHiC, species = "Mus musculus", genome = "mm10", focus_gene = "Krt5", cutoff = 0.01, gene_anno = gene_anno)
Arc plot visualization of enhancer-gene links for Krt14.
connections_Plot(results_SCEGHiC, species = "Mus musculus", genome = "mm10", focus_gene = "Krt14", cutoff = 0.01, gene_anno = gene_anno)
Coverage Plot visualizes chromatin accessibility around a target gene, including Hi-C interactions, scATAC-seq signals, aggregated ATAC-RNA correlations, eQTL SNPs, and enhancer–gene links predicted by SCEG-HiC. This facilitates intuitive comparison of regulatory interactions across multiple data layers.
We compare predicted enhancer-gene interactions with experimental Hi-C data from Basal cells (GSE197024) by visualizing coverage plots and computing the Pearson correlation coefficient between each gene and its candidate enhancers.The detailed code for this analysis is publicly available at the GitHub repository.
Coverage plot and visualize the links of Krt5 and Krt14.
# Load the truth of Basal data
truth_Basal <- readRDS("truth_Basal.rds")
## Load correlation data
correlation <- readRDS("correlation_Basal.rds")
# Coverage plot and visualize the links of Krt5
p1 <- coverPlot(skin, focus_gene = "Krt5", species = "Mus musculus", genome = "mm10", assay = "peaks", HIC_Result = truth_Basal, SCEG_HiC_Result = results_SCEGHiC, SCEG_HiC_cutoff = 0.01, correlation = correlation, cells = c("Basal", "Spinous", "Granular"), cellnames = "celltype")
# Coverage plot and visualize the links of Krt14
p2 <- coverPlot(skin, focus_gene = "Krt14", species = "Mus musculus", genome = "mm10", assay = "peaks", HIC_Result = truth_Basal, SCEG_HiC_Result = results_SCEGHiC, SCEG_HiC_cutoff = 0.01, correlation = correlation, cells = c("Basal", "Spinous", "Granular"), cellnames = "celltype")
patchwork::wrap_plots(p1, p2, ncol = 1)
sessionInfo()
## R version 4.4.2 (2024-10-31)
## Platform: x86_64-conda-linux-gnu
## Running under: Rocky Linux 9.6 (Blue Onyx)
##
## Matrix products: default
## BLAS/LAPACK: /home/liangxuan/conda/envs/test/lib/libopenblasp-r0.3.28.so; LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Asia/Shanghai
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] Matrix_1.6-5 dplyr_1.1.4
## [3] EnsDb.Mmusculus.v79_2.99.0 SCEGHiC_0.0.0.9000
## [5] SeuratDisk_0.0.0.9021 hdf5r_1.3.12
## [7] ggplot2_3.5.1 BSgenome.Hsapiens.UCSC.hg38_1.4.5
## [9] BSgenome_1.74.0 rtracklayer_1.66.0
## [11] BiocIO_1.16.0 Biostrings_2.74.1
## [13] XVector_0.46.0 EnsDb.Hsapiens.v86_2.99.0
## [15] ensembldb_2.30.0 AnnotationFilter_1.30.0
## [17] GenomicFeatures_1.58.0 AnnotationDbi_1.68.0
## [19] Biobase_2.66.0 GenomicRanges_1.58.0
## [21] GenomeInfoDb_1.42.1 IRanges_2.40.1
## [23] S4Vectors_0.44.0 BiocGenerics_0.52.0
## [25] Seurat_5.2.0 SeuratObject_5.0.2
## [27] sp_2.1-4 Signac_1.14.9001
##
## loaded via a namespace (and not attached):
## [1] R.methodsS3_1.8.2 dichromat_2.0-0.1
## [3] progress_1.2.3 urlchecker_1.0.1
## [5] nnet_7.3-20 goftest_1.2-3
## [7] vctrs_0.6.5 spatstat.random_3.3-2
## [9] digest_0.6.37 png_0.1-8
## [11] ggrepel_0.9.6 deldir_2.0-4
## [13] parallelly_1.41.0 MASS_7.3-64
## [15] reshape2_1.4.4 httpuv_1.6.15
## [17] withr_3.0.2 ggrastr_1.0.2
## [19] xfun_0.50 ellipsis_0.3.2
## [21] survival_3.8-3 commonmark_1.9.2
## [23] memoise_2.0.1 rcmdcheck_1.4.0
## [25] ggbeeswarm_0.7.2 profvis_0.4.0
## [27] systemfonts_1.1.0 ragg_1.3.3
## [29] zoo_1.8-12 pbapply_1.7-2
## [31] R.oo_1.27.0 Formula_1.2-5
## [33] prettyunits_1.2.0 KEGGREST_1.46.0
## [35] promises_1.3.2 httr_1.4.7
## [37] restfulr_0.0.15 globals_0.16.3
## [39] fitdistrplus_1.2-2 ps_1.8.1
## [41] rstudioapi_0.17.1 UCSC.utils_1.2.0
## [43] miniUI_0.1.1.1 generics_0.1.3
## [45] processx_3.8.5 base64enc_0.1-3
## [47] curl_6.0.1 zlibbioc_1.52.0
## [49] polyclip_1.10-7 xopen_1.0.1
## [51] GenomeInfoDbData_1.2.13 SparseArray_1.6.0
## [53] xtable_1.8-4 stringr_1.5.1
## [55] desc_1.4.3 evaluate_1.0.3
## [57] S4Arrays_1.6.0 BiocFileCache_2.14.0
## [59] hms_1.1.3 irlba_2.3.5.1
## [61] colorspace_2.1-1 filelock_1.0.3
## [63] ROCR_1.0-11 reticulate_1.40.0
## [65] spatstat.data_3.1-4 magrittr_2.0.3
## [67] lmtest_0.9-40 later_1.4.1
## [69] lattice_0.22-6 spatstat.geom_3.3-4
## [71] future.apply_1.11.3 scattermore_1.2
## [73] XML_3.99-0.17 cowplot_1.1.3
## [75] matrixStats_1.5.0 RcppAnnoy_0.0.22
## [77] Hmisc_5.2-2 pillar_1.10.1
## [79] nlme_3.1-166 cicero_1.3.9
## [81] compiler_4.4.2 RSpectra_0.16-2
## [83] stringi_1.8.7 tensor_1.5
## [85] minqa_1.2.8 SummarizedExperiment_1.36.0
## [87] devtools_2.4.5 GenomicAlignments_1.42.0
## [89] plyr_1.8.9 crayon_1.5.3
## [91] abind_1.4-8 bit_4.5.0.1
## [93] fastmatch_1.1-6 NCmisc_1.2.0
## [95] codetools_0.2-20 textshaping_1.0.1
## [97] monocle3_1.3.7 bslib_0.8.0
## [99] slam_0.1-55 biovizBase_1.54.0
## [101] plotly_4.10.4 mime_0.12
## [103] splines_4.4.2 Rcpp_1.0.14
## [105] fastDummies_1.7.4 dbplyr_2.5.0
## [107] interp_1.1-6 knitr_1.49
## [109] blob_1.2.4 lme4_1.1-36
## [111] fs_1.6.5 listenv_0.9.1
## [113] checkmate_2.3.2 Rdpack_2.6.2
## [115] pkgbuild_1.4.5 Gviz_1.50.0
## [117] tibble_3.2.1 callr_3.7.6
## [119] tweenr_2.0.3 pkgconfig_2.0.3
## [121] tools_4.4.2 cachem_1.1.0
## [123] rbibutils_2.3 RSQLite_2.3.9
## [125] viridisLite_0.4.2 DBI_1.2.3
## [127] fastmap_1.2.0 rmarkdown_2.29
## [129] scales_1.3.0 grid_4.4.2
## [131] usethis_3.1.0 ica_1.0-3
## [133] Rsamtools_2.22.0 sass_0.4.9
## [135] patchwork_1.3.0 FNN_1.1.4.1
## [137] dotCall64_1.2 VariantAnnotation_1.52.0
## [139] RANN_2.6.2 rpart_4.1.24
## [141] farver_2.1.2 reformulas_0.4.0
## [143] yaml_2.3.10 VGAM_1.1-12
## [145] roxygen2_7.3.3 latticeExtra_0.6-30
## [147] MatrixGenerics_1.18.1 foreign_0.8-88
## [149] cli_3.6.3 purrr_1.0.2
## [151] lifecycle_1.0.4 uwot_0.2.2
## [153] sessioninfo_1.2.2 backports_1.5.0
## [155] BiocParallel_1.40.0 gtable_0.3.6
## [157] rjson_0.2.23 ggridges_0.5.6
## [159] progressr_0.15.1 testthat_3.2.3
## [161] parallel_4.4.2 jsonlite_1.8.9
## [163] RcppHNSW_0.6.0 bitops_1.0-9
## [165] bit64_4.5.2 assertthat_0.2.1
## [167] brio_1.1.5 Rtsne_0.17
## [169] glasso_1.11 spatstat.utils_3.1-2
## [171] jquerylib_0.1.4 spatstat.univar_3.1-1
## [173] R.utils_2.12.3 lazyeval_0.2.2
## [175] shiny_1.10.0 htmltools_0.5.8.1
## [177] sctransform_0.4.1 rappdirs_0.3.3
## [179] glue_1.8.0 spam_2.11-0
## [181] httr2_1.0.7 RCurl_1.98-1.16
## [183] rprojroot_2.0.4 jpeg_0.1-10
## [185] gridExtra_2.3 boot_1.3-31
## [187] igraph_2.0.3 R6_2.5.1
## [189] tidyr_1.3.1 SingleCellExperiment_1.28.1
## [191] RcppRoll_0.3.1 labeling_0.4.3
## [193] cluster_2.1.8 pkgload_1.4.0
## [195] nloptr_2.1.1 DelayedArray_0.32.0
## [197] tidyselect_1.2.1 vipor_0.4.7
## [199] ProtGenerics_1.38.0 htmlTable_2.4.3
## [201] ggforce_0.4.2 xml2_1.5.0
## [203] vdiffr_1.0.8 future_1.34.0
## [205] munsell_0.5.1 KernSmooth_2.23-26
## [207] data.table_1.16.4 htmlwidgets_1.6.4
## [209] RColorBrewer_1.1-3 biomaRt_2.62.0
## [211] rlang_1.1.4 spatstat.sparse_3.1-0
## [213] spatstat.explore_3.3-4 remotes_2.5.0
## [215] reader_1.0.6 beeswarm_0.4.0